package cn.itcast.wanxinp2p.consumer.service.iml;

import cn.itcast.wanxinp2p.api.account.model.AccountDTO;
import cn.itcast.wanxinp2p.api.account.model.AccountRegisterDTO;
import cn.itcast.wanxinp2p.api.consumer.model.BankCardDTO;
import cn.itcast.wanxinp2p.api.consumer.model.ConsumerDTO;
import cn.itcast.wanxinp2p.api.consumer.model.ConsumerRegisterDTO;
import cn.itcast.wanxinp2p.api.depository.model.ConsumerRequest;
import cn.itcast.wanxinp2p.api.depository.model.GatewayRequest;
import cn.itcast.wanxinp2p.common.domain.*;
import cn.itcast.wanxinp2p.common.domain.consumer.ConsumerErrorCode;
import cn.itcast.wanxinp2p.common.util.CodeNoUtil;
import cn.itcast.wanxinp2p.consumer.agent.AccountApiAgent;
import cn.itcast.wanxinp2p.consumer.agent.DepositoryAgentApiAgent;
import cn.itcast.wanxinp2p.consumer.entity.BankCard;
import cn.itcast.wanxinp2p.consumer.entity.Consumer;
import cn.itcast.wanxinp2p.consumer.mapper.ConsumerMapper;
import cn.itcast.wanxinp2p.consumer.service.BankCardService;
import cn.itcast.wanxinp2p.consumer.service.ConsumerService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hmily.annotation.Hmily;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Slf4j
public class ConsumerServiceImpl extends ServiceImpl<ConsumerMapper, Consumer> implements ConsumerService {

    @Autowired
    private AccountApiAgent accountApiAgent;

    @Autowired
    private BankCardService bankCardService;


    @Autowired
    private DepositoryAgentApiAgent depositoryAgentApiAgent;

    @Override
    public Integer checkMobile(String mobile) {
        // 检查用户是否存在 1 存在（老用户）  0 不存在（新用户）
        return getByMobile(mobile) != null ? 1 : 0;
    }

    private ConsumerDTO getByMobile(String mobile) {
        // 根据手机号查询用户信息
        Consumer consumer = getOne(new QueryWrapper<Consumer>().lambda().eq(Consumer::getMobile, mobile));
        return convertConsumerEntityToDTO(consumer);
    }

    @Transactional
    @Override
    @Hmily(confirmMethod = "confirmRegister", cancelMethod = "cancelRegister")
    public void register(ConsumerRegisterDTO consumerRegisterDTO) {
        // 老用户
        if (checkMobile(consumerRegisterDTO.getMobile()) == 1) {
            throw new BusinessException(ConsumerErrorCode.E_140107);
        }
        // 创建实体consumer
        Consumer consumer = new Consumer();
        // 将前端传递的参数封装到consumer 实体类
        BeanUtils.copyProperties(consumerRegisterDTO, consumer);
        // 给用户自动设置一个编号作为用户名
        consumer.setUsername(CodeNoUtil.getNo(CodePrefixCode.CODE_NO_PREFIX));
        // 将生成后的用户名赋值给 consumerRegisterDTO （后面需要远程调用 account 账户服务）
        consumerRegisterDTO.setUsername(consumer.getUsername());
        // 设置用户编，（用户在存管系统标识）
        consumer.setUserNo(CodeNoUtil.getNo(CodePrefixCode.CODE_REQUEST_PREFIX));
        // 是否绑定银行卡 默认未绑定 0
        consumer.setIsBindCard(0);
        // 保存用户信息
        save(consumer);

        //远程调用account
        AccountRegisterDTO accountRegisterDTO = new AccountRegisterDTO();
        // 将consumerRegisterDTO 转换成 accountRegisterDTO
        BeanUtils.copyProperties(consumerRegisterDTO, accountRegisterDTO);


        // 调用 统一账户微服务 保存用户到 account表
        RestResponse<AccountDTO> restResponse = accountApiAgent.register(accountRegisterDTO);
        // 如果调用失败 抛出BusinessException 提示用户注册失败
        // BusinessException  是运行是异常，因此 事务会回滚。这种方式不是最终解决方案
        if (restResponse.getCode() != CommonErrorCode.SUCCESS.getCode()) {
            throw new BusinessException(ConsumerErrorCode.E_140106);
        }
    }

    //生成开户数据
    @Override
    public RestResponse<GatewayRequest> createConsumer(ConsumerRequest consumerRequest) {
        //根据用户手机号查询用户信息
        ConsumerDTO consumerDTO = this.getByMobile(consumerRequest.getMobile());

        //1判断用户是否已经开户
        if (consumerDTO.getIsBindCard() == 1) {
            throw new BusinessException(ConsumerErrorCode.E_140105); //用户已经开过户
        }

        //2判断银行卡号是否已经被绑定
        BankCardDTO bankCardDTO = bankCardService.getByCardNumber(consumerRequest.getCardNumber());
        if (bankCardDTO != null && bankCardDTO.getStatus() == StatusCode.STATUS_IN.getCode()) {
            throw new BusinessException(ConsumerErrorCode.E_140151); //该银行卡已经开过户
        }

        //3更新用户开户信息
       //3.1补充完整数据：id
        consumerRequest.setId(consumerDTO.getId());

        //3.2补充完善客户编号
        consumerRequest.setUserNo(CodeNoUtil.getNo(CodePrefixCode.CODE_CONSUMER_PREFIX));

        //3.3产生请求流水号和用户编号
        consumerRequest.setRequestNo(CodeNoUtil.getNo(CodePrefixCode.CODE_REQUEST_PREFIX));

        //4.更新用户中心的用户数据
        //4.1更新用户表数据

       /*
       全字段修改，没有值的属性会修改成null,这个不合理的
       LambdaQueryWrapper<Consumer> consumerLambdaQueryWrapper = new LambdaQueryWrapper<>();
       consumerLambdaQueryWrapper.eq(Consumer::getMobile,consumerRequest.getMobile());

       Consumer consumer=new Consumer();
       BeanUtils.copyProperties(consumerRequest,consumer);

       this.update(consumer,consumerLambdaQueryWrapper);*/


        LambdaUpdateWrapper<Consumer> consumerLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        consumerLambdaUpdateWrapper.eq(Consumer::getMobile,consumerRequest.getMobile());
        consumerLambdaUpdateWrapper.set(Consumer::getUserNo,consumerRequest.getRequestNo());
        consumerLambdaUpdateWrapper.set(Consumer::getFullname,consumerRequest.getFullname());
        consumerLambdaUpdateWrapper.set(Consumer::getRequestNo,consumerRequest.getRequestNo());
        consumerLambdaUpdateWrapper.set(Consumer::getIdNumber,consumerRequest.getIdNumber());
        consumerLambdaUpdateWrapper.set(Consumer::getAuthList,"ALL");
        this.update(consumerLambdaUpdateWrapper);



        //4.2更新银行卡数据
        BankCard bankCard = new BankCard();
        bankCard.setBankCode(consumerRequest.getBankCode());
        bankCard.setBankName(consumerRequest.getFullname());
        bankCard.setMobile(consumerRequest.getMobile());
        bankCard.setStatus(StatusCode.STATUS_OUT.getCode()); //银行卡号未激活
        bankCard.setCardNumber(consumerRequest.getIdNumber());
        //4.3根据用户id去银行卡账户查询该用户是否存在该英航卡 (一个用户手机号只能绑定一个银行卡号)
        BankCardDTO cardDTO = bankCardService.getByConsumerId(bankCard.getConsumerId());
        if(!ObjectUtils.isEmpty(cardDTO)){
            bankCard.setId(cardDTO.getId());
        }
        bankCardService.saveOrUpdate(bankCard);

        //


        return depositoryAgentApiAgent.createConsumer(consumerRequest);
    }

    @Override
    public Boolean modifyResult(DepositoryConsumerResponse response) {

        //1.获取状态
        int status = DepositoryReturnCode.RETURN_CODE_00000.getCode()
                .equals(response.getRespCode()) ? StatusCode.STATUS_IN.getCode()
                :StatusCode.STATUS_FAIL.getCode();
        //2.更新开户结果
        Consumer consumer = getByRequestNo(response.getRequestNo());
        update(Wrappers.<Consumer>lambdaUpdate().eq(Consumer::getId, consumer.getId())
                .set(Consumer::getIsBindCard, status).set(Consumer::getStatus, status));
        //3.更新银行卡信息
        return bankCardService.update(Wrappers.<BankCard>lambdaUpdate()
                .eq(BankCard::getConsumerId, consumer.getId())
                .set(BankCard::getStatus, status).set(BankCard::getBankCode,
                        response.getBankCode())
                .set(BankCard::getBankName, response.getBankName()));
    }

    private Consumer getByRequestNo(String requestNo){
        return getOne(Wrappers.<Consumer>lambdaQuery().eq(Consumer::getRequestNo,requestNo));
    }


    public void confirmRegister(ConsumerRegisterDTO consumerRegisterDTO) {
        log.info("execute confirmRegister");
    }

    public void cancelRegister(ConsumerRegisterDTO consumerRegisterDTO) {
        log.info("execute cancelRegister");
        remove(Wrappers.<Consumer>lambdaQuery().eq(Consumer::getMobile,
                consumerRegisterDTO.getMobile()));
    }


    /**
     * entity转为dto
     *
     * @param entity
     * @return
     **/
    private ConsumerDTO convertConsumerEntityToDTO(Consumer entity) {
        if (entity == null) {
            return null;
        }
        ConsumerDTO dto = new ConsumerDTO();
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }

}
